<?php

define("MPD_OK",			"OK");
define("MPD_SPACE",			" ");
define("MPD_ADD",			"add");
define("MPD_LS",			"lsinfo");
define("MPD_CLEAR",			"clear");
define("MPD_VOL",			"setvol");
define("MPD_PLAY",			"play");
define("MPD_RANDOM_ON",		"random 1");
define("MPD_RANDOM_OFF",	"random 0");
define("MPD_STOP",			"stop");
define("MPD_STATUS",		"status");
define("MPD_NEXT",			"next");
define("MPD_PREVIOUS",		"previous");
define("MPD_PAUSE",			"pause");


class MPD {
	var $host;
	var $port;
	var $mpd_sock = null;
	var $status = array();
	var $radios = array();

	function MPD($timeout=10,$prefix_library='/Library/') {
		$this->timeout = $timeout;
		$this->connected = false;
		$this->prefix_library = $prefix_library;
	}

	function initRadios($radios_db){
		$fh = fopen($radios_db,'r');
		while ($line = fgets($fh)) {
			$line = trim($line);
			list ( $name, $url ) = explode (';', $line);
			$this->radios[$name] = $url;
		}
		fclose($fh);
		return $this->radios;
	}

	function getStatus() {
		if ( is_null( $rsp = $this->sendCommand(MPD_STATUS) ) ) return null;

		$statusLine = strtok($rsp,"\n");
		while ( $statusLine ) {
			list ( $element, $value ) = explode(": ",$statusLine);
			if ( $element == 'state') { 
				if ( $value == 'stop') {
					$this->status[$element] = 'stopped';
				} elseif ( $value == 'play') {
					$this->status[$element] = 'playing';
				} elseif ( $value == 'pause') {
					$this->status[$element] = 'paused';
				} else {
					$this->status[$element] = $value;
				}
			} else {
				$this->status[$element] = $value;
			}
			$statusLine = strtok("\n");
		}
		return $this->status;
	}

	function getState() {
		if ( is_null( $rsp = $this->getStatus() ) ) return null;
		return $this->status['state'];
	}

	function getVolume() {
		if ( is_null( $rsp = $this->getStatus() ) ) return null;
		return $this->status['volume'];
	}

	function connect($srv,$port) {
		$this->host = $srv;
		$this->port = $port;
		$this->mpd_sock = fsockopen($this->host,$this->port,$errno, $errstr,$this->timeout);
		if (!$this->mpd_sock) {
			error_log( "$errstr ($errno)<br />\n" );
			return null;
		} else {
				while(!feof($this->mpd_sock)) {
					$rsp =  fgets($this->mpd_sock,1024);
					if (strncmp(MPD_OK,$rsp,strlen(MPD_OK)) == 0) {
						$this->connected = true;
						return $rsp;
					} else {
						break;
					}
				}
				// close socket
				fclose($this->mpd_sock);
				return null;
		}
	}

	function sendCommand($cmd) {
		if ( ! $this->connected ) {
			error_log('not connected');
			return null;
		} else {
			$respStr = "";
			fputs($this->mpd_sock,"$cmd\n");
			while(!feof($this->mpd_sock)) {
				$response = fgets($this->mpd_sock,1024);

				// complete response received
				if (strncmp(MPD_OK,$response,strlen(MPD_OK)) == 0) {
					break;
				}
				
				$respStr .= $response;

			}
			return $respStr;
		}
	}

	function nextPlay(){
		if ( is_null( $rsp = $this->sendCommand(MPD_NEXT) ) ) return null;
		return $rsp;
	}

	function previousPlay(){
		if ( is_null( $rsp = $this->sendCommand(MPD_PREVIOUS) ) ) return null;
		return $rsp;
	}

	function stopPlay(){
		if ( is_null( $rsp = $this->sendCommand(MPD_STOP) ) ) return null;
		return $rsp;
	}

	function pausePlay(){
		if ( is_null( $rsp = $this->sendCommand(MPD_PAUSE) ) ) return null;
		return $rsp;
	}

	function startPlay($id, $random=false){
		if ( $random == false ) {
			if ( is_null( $rsp = $this->sendCommand(MPD_RANDOM_OFF) ) ) return null;
		} else {
			if ( is_null( $rsp = $this->sendCommand(MPD_RANDOM_ON) ) ) return null;
		}
		if ( is_null( $rsp = $this->sendCommand(MPD_PLAY.MPD_SPACE.$id) ) ) return null;
		return $rsp;
	}

	function volumeDown($down) {
		if ( is_null( $rsp = $this->getStatus() ) ) return null;
		
		$val = intval($this->getVolume())-$down;
		if ( is_null( $rsp = $this->sendCommand(MPD_VOL.MPD_SPACE.$val) ) ) return null;

		return $rsp;
	}

	function volumeUp($up) {
		if ( is_null( $rsp = $this->getStatus() ) ) return null;
		
		$val = intval($this->getVolume())+$up;
		error_log($val);
		if ( is_null( $rsp = $this->sendCommand(MPD_VOL.MPD_SPACE.$val) ) ) return null;

		return $rsp;
	}

	function clearPlaylist() {
		if ( is_null( $rsp = $this->sendCommand(MPD_CLEAR) ) ) return null;
		return $rsp;
	}

	function appendPlaylist($stream) {
		$stream = ltrim ($stream, $this->prefix_library );
		$stream = rtrim ($stream, '/');
		if ( is_null( $rsp = $this->sendCommand(MPD_ADD.MPD_SPACE.'"'.$stream.'"') ) ) return null;
		return $rsp;
	}

	function listDir($dir){
		$dir = ltrim ($dir, $this->prefix_library );
		$dir = rtrim ($dir,'/');

		if ( is_null( $rsp = $this->sendCommand(MPD_LS.MPD_SPACE.'"'.$dir.'"') ) ) return null;
		$folders = array();
		$dirLine = strtok($rsp,"\n");

		while ( $dirLine ) {
			list ( $element, $value ) = explode(": ",$dirLine);
			if ( strlen ( $dir  ) == 0) {
				$abs_dir = $value;
			} else {
				list ( $left, $abs_dir ) = explode($dir."/",$value);
			}
			$folders[ $abs_dir ] = $element;
			$dirLine = strtok("\n");
		}
		return $folders;
	}
}

?>